#define UNICODE
#define _UNICODE
#include <windows.h>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <map>
#include <commctrl.h>
#include <commdlg.h>
#include <locale>
#include <codecvt>
#include "lexer.h"

#pragma comment(lib, "comctl32.lib")
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

// 资源ID
#define IDM_FILE_OPEN_GRAMMAR 1001
#define IDM_FILE_OPEN_SOURCE 1002
#define IDM_FILE_ANALYZE 1003
#define IDM_FILE_SAVE 1004
#define IDM_FILE_EXIT 1005
#define IDM_HELP_ABOUT 2001

std::vector<Token> tokens;
HWND hList = NULL;
HWND hGrammarPath = NULL;
HWND hSourcePath = NULL;
HWND hStatus = NULL;
HFONT hFont = NULL;
Lexer* lexer = nullptr;
const int PADDING = 10;
const int BUTTON_HEIGHT = 30;
const int EDIT_HEIGHT = 25;

// 函数声明
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void AddControls(HWND hwnd);
void LoadFile(HWND hwnd, HWND hEdit, bool isGrammar);
void AnalyzeFile(HWND hwnd);
void SaveResults(HWND hwnd);
void CreateMenuBar(HWND hwnd);
HFONT CreateCustomFont();
void ShowAboutDialog(HWND hwnd);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) {
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    
    lexer = new Lexer();

    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_BAR_CLASSES;
    InitCommonControlsEx(&icex);

    const wchar_t CLASS_NAME[] = L"LexicalAnalyzer";
    
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    
    // 加载图标
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    
    RegisterClass(&wc);

    // 获取屏幕尺寸以计算窗口位置
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
    int windowWidth = 1000;
    int windowHeight = 700;
    int windowX = (screenWidth - windowWidth) / 2;
    int windowY = (screenHeight - windowHeight) / 2;

    HWND hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        CLASS_NAME,
        L"词法分析器",
        WS_OVERLAPPEDWINDOW,
        windowX, windowY, windowWidth, windowHeight,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (hwnd == NULL) {
        return 0;
    }

    // 创建自定义字体
    hFont = CreateCustomFont();

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    DeleteObject(hFont);
    delete lexer;
    return 0;
}

HFONT CreateCustomFont() {
    return CreateFont(
        -14,                    // 高度
        0,                      // 宽度
        0,                      // 角度
        0,                      // 基线角度
        FW_NORMAL,             // 字重
        FALSE,                 // 斜体
        FALSE,                 // 下划线
        FALSE,                 // 删除线
        DEFAULT_CHARSET,       // 字符集
        OUT_DEFAULT_PRECIS,    // 输出精度
        CLIP_DEFAULT_PRECIS,   // 裁剪精度
        CLEARTYPE_QUALITY,     // 输出质量
        DEFAULT_PITCH | FF_DONTCARE, // 字体间距和族
        L"微软雅黑"           // 字体名称
    );
}

void CreateMenuBar(HWND hwnd) {
    HMENU hMenu = CreateMenu();
    HMENU hFileMenu = CreatePopupMenu();
    HMENU hHelpMenu = CreatePopupMenu();

    AppendMenu(hFileMenu, MF_STRING, IDM_FILE_OPEN_GRAMMAR, L"打开文法文件(&G)");
    AppendMenu(hFileMenu, MF_STRING, IDM_FILE_OPEN_SOURCE, L"打开源文件(&S)");
    AppendMenu(hFileMenu, MF_SEPARATOR, 0, NULL);
    AppendMenu(hFileMenu, MF_STRING, IDM_FILE_ANALYZE, L"开始分析(&A)");
    AppendMenu(hFileMenu, MF_STRING, IDM_FILE_SAVE, L"保存结果(&R)");
    AppendMenu(hFileMenu, MF_SEPARATOR, 0, NULL);
    AppendMenu(hFileMenu, MF_STRING, IDM_FILE_EXIT, L"退出(&X)");

    AppendMenu(hHelpMenu, MF_STRING, IDM_HELP_ABOUT, L"关于(&A)");

    AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"文件(&F)");
    AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hHelpMenu, L"帮助(&H)");

    SetMenu(hwnd, hMenu);
}

void AddControls(HWND hwnd) {
    // 创建菜单栏
    CreateMenuBar(hwnd);

    // 创建分组框
    HWND hGroupBox = CreateWindow(
        L"BUTTON", L"文件选择", 
        WS_VISIBLE | WS_CHILD | BS_GROUPBOX,
        PADDING, PADDING, 960, 90, 
        hwnd, NULL, NULL, NULL
    );
    SendMessage(hGroupBox, WM_SETFONT, (WPARAM)hFont, TRUE);

    // 文法文件控件
    CreateWindow(L"STATIC", L"文法：", 
        WS_VISIBLE | WS_CHILD,
        PADDING + 10, PADDING + 25, 70, 20, 
        hwnd, NULL, NULL, NULL);
    
    hGrammarPath = CreateWindow(L"EDIT", L"", 
        WS_VISIBLE | WS_CHILD | WS_BORDER | ES_READONLY,
        PADDING + 80, PADDING + 22, 740, EDIT_HEIGHT, 
        hwnd, NULL, NULL, NULL);
    
    HWND hBtnGrammar = CreateWindow(L"BUTTON", L"浏览...", 
        WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
        PADDING + 830, PADDING + 20, 100, BUTTON_HEIGHT, 
        hwnd, (HMENU)IDM_FILE_OPEN_GRAMMAR, NULL, NULL);

    // 源文件控件
    CreateWindow(L"STATIC", L"代码段：", 
        WS_VISIBLE | WS_CHILD,
        PADDING + 10, PADDING + 55, 70, 20, 
        hwnd, NULL, NULL, NULL);
    
    hSourcePath = CreateWindow(L"EDIT", L"", 
        WS_VISIBLE | WS_CHILD | WS_BORDER | ES_READONLY,
        PADDING + 80, PADDING + 52, 740, EDIT_HEIGHT, 
        hwnd, NULL, NULL, NULL);
    
    HWND hBtnSource = CreateWindow(L"BUTTON", L"浏览...", 
        WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
        PADDING + 830, PADDING + 50, 100, BUTTON_HEIGHT, 
        hwnd, (HMENU)IDM_FILE_OPEN_SOURCE, NULL, NULL);

    // 获取程序所在目录
    wchar_t exePath[MAX_PATH];
    GetModuleFileName(NULL, exePath, MAX_PATH);
    wchar_t* lastSlash = wcsrchr(exePath, L'\\');
    if (lastSlash) {
        *lastSlash = L'\0';  // 去掉文件名，只保留目录
    }

    // 设置默认文件路径（使用绝对路径）
    wchar_t defaultGrammarPath[MAX_PATH];
    wchar_t defaultSourcePath[MAX_PATH];
    swprintf_s(defaultGrammarPath, L"%s\\..\\res\\grammar.txt", exePath);
    swprintf_s(defaultSourcePath, L"%s\\..\\test\\test.cpp", exePath);
    
    // 检查文件是否存在
    if (GetFileAttributes(defaultGrammarPath) != INVALID_FILE_ATTRIBUTES) {
        SetWindowText(hGrammarPath, defaultGrammarPath);
    }
    
    if (GetFileAttributes(defaultSourcePath) != INVALID_FILE_ATTRIBUTES) {
        SetWindowText(hSourcePath, defaultSourcePath);
    }

    // 操作按钮
    HWND hBtnAnalyze = CreateWindow(L"BUTTON", L"开始分析", 
        WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
        PADDING, PADDING + 100, 100, BUTTON_HEIGHT, 
        hwnd, (HMENU)IDM_FILE_ANALYZE, NULL, NULL);

    HWND hBtnSave = CreateWindow(L"BUTTON", L"保存结果", 
        WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
        PADDING + 110, PADDING + 100, 100, BUTTON_HEIGHT, 
        hwnd, (HMENU)IDM_FILE_SAVE, NULL, NULL);

    // 列表视图
    hList = CreateWindow(WC_LISTVIEW, L"", 
        WS_VISIBLE | WS_CHILD | LVS_REPORT | WS_BORDER | LVS_SHOWSELALWAYS,
        PADDING, PADDING + 140, 960, 460, 
        hwnd, NULL, NULL, NULL);

    // 设置列表视图扩展样式
    ListView_SetExtendedListViewStyle(hList, 
        LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER);

    LVCOLUMN lvc = {0};
    lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
    lvc.fmt = LVCFMT_LEFT;
    
    lvc.pszText = (LPWSTR)L"行号";
    lvc.cx = 100;
    ListView_InsertColumn(hList, 0, &lvc);
    
    lvc.pszText = (LPWSTR)L"类别";
    lvc.cx = 300;
    ListView_InsertColumn(hList, 1, &lvc);
    
    lvc.pszText = (LPWSTR)L"内容";
    lvc.cx = 540;
    ListView_InsertColumn(hList, 2, &lvc);

    // 状态栏
    hStatus = CreateWindow(STATUSCLASSNAME, NULL,
        WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
        0, 0, 0, 0, 
        hwnd, NULL, NULL, NULL);

    // 为所有控件设置字体
    EnumChildWindows(hwnd, [](HWND hwndChild, LPARAM lParam) -> BOOL {
        SendMessage(hwndChild, WM_SETFONT, (WPARAM)lParam, TRUE);
        return TRUE;
    }, (LPARAM)hFont);
}

void ShowAboutDialog(HWND hwnd) {
    MessageBox(hwnd, 
        L"词法分析器 1.0版本\n\n"
        L"一个简单的词法分析工具\n"
        L"支持自定义文法规则\n\n"
        L"作者：刘健顺\n"
        L"日期：2025年4.14",
        L"关于词法分析器",
        MB_OK | MB_ICONINFORMATION);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CREATE:
            AddControls(hwnd);
            return 0;

        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                case IDM_FILE_OPEN_GRAMMAR:
                    LoadFile(hwnd, hGrammarPath, true);
                    break;
                case IDM_FILE_OPEN_SOURCE:
                    LoadFile(hwnd, hSourcePath, false);
                    break;
                case IDM_FILE_ANALYZE:
                    AnalyzeFile(hwnd);
                    break;
                case IDM_FILE_SAVE:
                    SaveResults(hwnd);
                    break;
                case IDM_FILE_EXIT:
                    DestroyWindow(hwnd);
                    break;
                case IDM_HELP_ABOUT:
                    ShowAboutDialog(hwnd);
                    break;
            }
            return 0;

        case WM_SIZE:
            // 调整状态栏大小
            SendMessage(hStatus, WM_SIZE, 0, 0);
            return 0;

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

void LoadFile(HWND hwnd, HWND hEdit, bool isGrammar) {
    wchar_t filename[MAX_PATH] = {0};
    OPENFILENAME ofn = {0};
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = filename;
    ofn.nMaxFile = sizeof(filename)/sizeof(wchar_t);
    ofn.lpstrFilter = isGrammar ? L"文本文件\0*.txt\0所有文件\0*.*\0" : L"C++文件\0*.cpp;*.h\0所有文件\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    if (GetOpenFileName(&ofn)) {
        SetWindowText(hEdit, filename);
    }
}

void AnalyzeFile(HWND hwnd) {
    wchar_t grammarPath[MAX_PATH] = {0};
    wchar_t sourcePath[MAX_PATH] = {0};
    GetWindowText(hGrammarPath, grammarPath, MAX_PATH);
    GetWindowText(hSourcePath, sourcePath, MAX_PATH);

    if (wcslen(grammarPath) == 0 || wcslen(sourcePath) == 0) {
        MessageBox(hwnd, L"请先选择文法文件和源文件", L"错误", MB_OK | MB_ICONERROR);
        return;
    }

    try {
        // 转换Unicode路径为UTF-8
        char grammarPathUtf8[MAX_PATH] = {0};
        char sourcePathUtf8[MAX_PATH] = {0};
        WideCharToMultiByte(CP_UTF8, 0, grammarPath, -1, grammarPathUtf8, MAX_PATH, NULL, NULL);
        WideCharToMultiByte(CP_UTF8, 0, sourcePath, -1, sourcePathUtf8, MAX_PATH, NULL, NULL);

        lexer->loadGrammar(grammarPathUtf8);
        tokens = lexer->analyze(sourcePathUtf8);

        ListView_DeleteAllItems(hList);

        for (size_t i = 0; i < tokens.size(); i++) {
            LVITEM lvi = {0};
            lvi.mask = LVIF_TEXT;
            lvi.iItem = i;

            // 行号
            wchar_t lineStr[32];
            _snwprintf_s(lineStr, _countof(lineStr), _TRUNCATE, L"%d", tokens[i].line);
            lvi.iSubItem = 0;
            lvi.pszText = lineStr;
            ListView_InsertItem(hList, &lvi);

            // 类别
            wchar_t typeStr[256];
            MultiByteToWideChar(CP_UTF8, 0, tokens[i].type.c_str(), -1, typeStr, 256);
            lvi.iSubItem = 1;
            lvi.pszText = typeStr;
            ListView_SetItem(hList, &lvi);

            // 内容
            wchar_t contentStr[256];
            MultiByteToWideChar(CP_UTF8, 0, tokens[i].content.c_str(), -1, contentStr, 256);
            lvi.iSubItem = 2;
            lvi.pszText = contentStr;
            ListView_SetItem(hList, &lvi);
        }

        SetWindowText(hStatus, L"分析完成");
    }
    catch (const std::exception& e) {
        wchar_t errorMsg[512];
        MultiByteToWideChar(CP_UTF8, 0, e.what(), -1, errorMsg, 512);
        MessageBox(hwnd, errorMsg, L"错误", MB_OK | MB_ICONERROR);
    }
}

void SaveResults(HWND hwnd) {
    if (tokens.empty()) {
        MessageBox(hwnd, L"没有可保存的分析结果", L"提示", MB_OK | MB_ICONINFORMATION);
        return;
    }

    wchar_t filename[MAX_PATH] = {0};
    OPENFILENAME ofn = {0};
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = filename;
    ofn.nMaxFile = sizeof(filename)/sizeof(wchar_t);
    ofn.lpstrFilter = L"文本文件\0*.txt\0所有文件\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_OVERWRITEPROMPT;
    ofn.lpstrDefExt = L"txt";

    if (GetSaveFileName(&ofn)) {
        // 转换Unicode路径为UTF-8
        char filenameUtf8[MAX_PATH] = {0};
        WideCharToMultiByte(CP_UTF8, 0, filename, -1, filenameUtf8, MAX_PATH, NULL, NULL);

        // 使用UTF-8编码保存文件
        std::ofstream outFile;
        outFile.open(filenameUtf8, std::ios::out | std::ios::binary);
        
        if (!outFile) {
            MessageBox(hwnd, L"无法创建文件", L"错误", MB_OK | MB_ICONERROR);
            return;
        }

        // 写入UTF-8 BOM
        outFile.write("\xEF\xBB\xBF", 3);

        for (const auto& token : tokens) {
            char lineStr[32];
            sprintf_s(lineStr, "%d", token.line);
            
            outFile << "<" << lineStr << ", " << token.type << ", \"" << token.content << "\">" << std::endl;
        }

        outFile.close();
        MessageBox(hwnd, L"保存成功", L"提示", MB_OK | MB_ICONINFORMATION);
    }
} 